﻿using UnityEngine;
using System.Collections.Generic;
using LuaInterface;
using System.IO;

namespace YanhuaMMO {
    public class LuaManager : Manager {
        private LuaState _lua;
        private LuaLoader _loader;
        private LuaLooper _loop = null;
        public LuaTable luaData = null;
        public static LuaManager Instance;

        public static ObjectTranslator _translator = null;

        // Use this for initialization
        void Awake() {
            Instance = this;
            _loader = new LuaLoader();
            _lua = new LuaState();
            _translator = LuaState.GetTranslator(_lua.L);
            this.OpenLibs();
            _lua.LuaSetTop(0);

            LuaBinder.Bind(_lua);
            DelegateFactory.Init();
            LuaCoroutine.Register(_lua, this);
        }

        public LuaState GetStatePtr()
        {
            return _lua;
        }

        public void InitStart() {
            InitLuaPath();
            InitLuaBundle();
            _lua.Start();    //启动LUAVM
            StartMain();
            StartLooper();
            // InitLuaData();
        }

        void StartLooper() {
            _loop = gameObject.AddComponent<LuaLooper>();
            _loop.luaState = _lua;
        }

        //cjson 比较特殊，只new了一个table，没有注册库，这里注册一下
        protected void OpenCJson() {
            _lua.LuaGetField(LuaIndexes.LUA_REGISTRYINDEX, "_LOADED");
            _lua.OpenLibs(LuaDLL.luaopen_cjson);
            _lua.LuaSetField(-2, "cjson");

            _lua.OpenLibs(LuaDLL.luaopen_cjson_safe);
            _lua.LuaSetField(-2, "cjson.safe");
        }

        void StartMain() {
            _lua.DoFile("Main.lua");

            var main = _lua.GetFunction("Main");
            main.Call();
            main.Dispose();
            this.updateFunc = _lua.GetFunction("LuaUpdate");
            this.netRecvFunc = _lua.GetFunction("NetDataRecv");
        }

        private LuaFunction updateFunc = null;
        private void Update()
        { 
            if( this.updateFunc != null)
            {
                updateFunc.BeginPCall();
                updateFunc.Push(Time.deltaTime);
                updateFunc.PCall();
                updateFunc.EndPCall();
                _lua.Collect();
            }
        }

        private LuaFunction netRecvFunc = null;
        public void RecvNetMessage( int msg_id, ByteBuffer buff)
        {
            if (this.netRecvFunc != null)
            {
                netRecvFunc.BeginPCall();
                netRecvFunc.Push(msg_id);
                netRecvFunc.Push(buff);
                netRecvFunc.PCall();
                netRecvFunc.EndPCall();
            }
        }

        public void LuaLoadBuffer(string str, string chunkName)
        {
            var buffer = System.Text.Encoding.Default.GetBytes(str);
            _lua.LuaLoadBuffer(buffer, buffer.Length, chunkName);
        }

    #region luaide 调试库添加
    //如果项目中没有luasocket 请打开
    [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
    static int LuaOpen_Socket_Core(System.IntPtr L)
    {
        return LuaDLL.luaopen_socket_core(L);
    }

    protected void OpenLuaSocket()
    {
        LuaConst.openLuaSocket = true;
        _lua.BeginPreLoad();
        _lua.RegFunction("socket.core", LuaOpen_Socket_Core);
        _lua.EndPreLoad();
    }
    #endregion

    /// <summary>
    /// 初始化加载第三方库
    /// </summary>
    void OpenLibs() {
        _lua.OpenLibs(LuaDLL.luaopen_pb);      
        // lua.OpenLibs(LuaDLL.luaopen_sproto_core);
        // lua.OpenLibs(LuaDLL.luaopen_protobuf_c);
        _lua.OpenLibs(LuaDLL.luaopen_lpeg);
        _lua.OpenLibs(LuaDLL.luaopen_bit);


        //luaide socket 开启
        _lua.OpenLibs(LuaDLL.luaopen_socket_core); 
        this.OpenLuaSocket();
        //end luaide        


        this.OpenCJson();

        _lua.OpenLibs(LuaDLL.luaopen_socket_core);
    }

        /// <summary>
        /// 初始化Lua代码加载路径
        /// </summary>
        void InitLuaPath() {
            if (!AppConst.BundleMode) {
                var rootPath = AppConst.FrameworkRoot;
                _lua.AddSearchPath(rootPath + "/Lua");
                _lua.AddSearchPath(rootPath + "/ToLua/Lua");
            }
            else {
                var DataPath = Util.DataPath + "lua";
                var ResPath = Util.AppContentPath() + "lua";
                _lua.AddSearchPath(DataPath);
                //lua.AddSearchPath(ResPath);
            }
        }

        /// <summary>
        /// 初始化LuaBundle
        /// </summary>
        void InitLuaBundle() {
            //如果是bundle模式
            if (!AppConst.BundleMode) return;
            var list = new List<string>();
            ResManager.LoadLuaAssetBundleList(list);
            foreach (var file in list)
            {
                if (file.Length <= 0) continue;
                var bundleName = Path.GetFileNameWithoutExtension(file);
                //Util.Log("bundleName:" + bundleName + " path:" + file);
                var bundle = ResManager.LoadAssetBundleFromFile(bundleName, file);
                if (bundle != null)
                {
                    _loader.AddSearchBundle(bundleName.ToLower(), bundle);
                    //Util.Log("bundleName:" + bundleName + " path:" + file);
                }
            }
            return;
        }

        public void DoFile(string filename) {
            _lua.DoFile(filename);
        }

        // Update is called once per frame
        public object[] CallFunction(string funcName, params object[] args) {
            var func = _lua.GetFunction(funcName);
            return func != null ? func.LazyCall(args) : null;
        }

        [NoToLua]
        public LuaTable GetTable(string luaTable) 
        {
            return _lua.GetTable(luaTable,false);
        }
        [NoToLua]
        public LuaFunction GetLuaFunction(string funcName) 
        {
            return _lua.GetFunction(funcName);
        }

        public LuaTable lookTable(string tableName)
        {
            return _lua.GetTable(tableName);
        }

        public void LuaGC() {
            _lua.LuaGC(LuaGCOptions.LUA_GCCOLLECT);
        }

        public void Close() {
            _loop.Destroy();
            _loop = null;

            if (this.updateFunc != null)
            {
                this.updateFunc.Dispose();
                this.updateFunc = null;
            }
            
                
            if (this.netRecvFunc != null)
            {
                this.netRecvFunc.Dispose();
                this.netRecvFunc = null;
            }

            _lua.Dispose();
            _lua = null;
            _loader = null;
        }


        //CSharpModel初始化
        public void InitLuaData()
        {
            _lua.DoFile("model/CSharpModel.lua");
            var data = CallFunction("CSharpModel.Get", null);
            luaData = data[0] as LuaTable;
        }
        //获得CSharpModel成员变量
        public object GetValue(string value)
        {
            return luaData[value];
        }
        //调用CSharpModel成员函数
        public object[] CallFunc(string funcName, object[] args = null)
        {
            if (luaData[funcName] == null) return null;
            var func = luaData[funcName] as LuaFunction;
            return func.LazyCall((object)args);
        }
    }
}